Update windows to build with new APIs and first cut at preview work.
authorAlexander Larsson <alexl@redhat.com>
Thu, 8 Jun 2006 09:09:50 +0000 (09:09 +0000)
committerAlexander Larsson <alexl@src.gnome.org>
Thu, 8 Jun 2006 09:09:50 +0000 (09:09 +0000)
2006-06-08  Alexander Larsson  <alexl@redhat.com>

* gtk/gtkprintoperation-win32.c:
Update windows to build with new APIs and first cut
at preview work.

* gtk/gtkprintoperation-private.h:
* gtk/gtkprintoperation-unix.c:
* gtk/gtkprintoperation.c
Various updates needed when making the preview work on win32.

* tests/print-editor.c:
Print, don't preview.

ChangeLog
ChangeLog.pre-2-10
gtk/gtkprintoperation-private.h
gtk/gtkprintoperation-unix.c
gtk/gtkprintoperation-win32.c
gtk/gtkprintoperation.c
tests/print-editor.c

index 0f68b3992bf97b94cdefe10a0604a4db2651b4bf..188b2a1370c15d6aabd73398f4263568354800d4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2006-06-08  Alexander Larsson  <alexl@redhat.com>
+
+       * gtk/gtkprintoperation-win32.c:
+       Update windows to build with new APIs and first cut
+       at preview work.
+       
+       * gtk/gtkprintoperation-private.h:
+       * gtk/gtkprintoperation-unix.c:
+       * gtk/gtkprintoperation.c
+       Various updates needed when making the preview work on win32.
+
+       * tests/print-editor.c:
+       Print, don't preview.
+
 2006-06-07  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkentry.c (popup_targets_received): Make Delete
index 0f68b3992bf97b94cdefe10a0604a4db2651b4bf..188b2a1370c15d6aabd73398f4263568354800d4 100644 (file)
@@ -1,3 +1,17 @@
+2006-06-08  Alexander Larsson  <alexl@redhat.com>
+
+       * gtk/gtkprintoperation-win32.c:
+       Update windows to build with new APIs and first cut
+       at preview work.
+       
+       * gtk/gtkprintoperation-private.h:
+       * gtk/gtkprintoperation-unix.c:
+       * gtk/gtkprintoperation.c
+       Various updates needed when making the preview work on win32.
+
+       * tests/print-editor.c:
+       Print, don't preview.
+
 2006-06-07  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkentry.c (popup_targets_received): Make Delete
index 73f44e5353c7cb1238613c43d075ed1e0e0c5393..a727da4aceab3bfc2f9f8e0a9957962deb4ff8b6 100644 (file)
@@ -50,10 +50,6 @@ struct _GtkPrintOperationPrivate
 
   GtkPrintContext *print_context;
   
-  /* Data for the print job: */
-  /* cairo_surface_t *surface; */
-  /*  gdouble dpi_x, dpi_y; */
-
   GtkPrintPages print_pages;
   GtkPageRange *page_ranges;
   gint num_page_ranges;
@@ -97,16 +93,23 @@ void                    _gtk_print_operation_platform_backend_run_dialog_async
                                                                                      GtkWindow                   *parent,
                                                                                      GtkPrintOperationPrintFunc   print_cb);
 void                    _gtk_print_operation_platform_backend_launch_preview         (GtkPrintOperation           *op,
+                                                                                     cairo_surface_t             *surface,
                                                                                      GtkWindow                   *parent,
                                                                                      const char                  *filename);
 cairo_surface_t *       _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation           *op,
                                                                                      GtkPageSetup                *page_setup,
                                                                                      gdouble                     *dpi_x,
                                                                                      gdouble                     *dpi_y,
-                                                                                     const gchar                 *target);
+                                                                                     gchar                       **target);
 void                    _gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation           *op,
                                                                                      GtkPageSetup                *page_setup,
                                                                                      cairo_surface_t             *surface);
+void                    _gtk_print_operation_platform_backend_preview_start_page     (GtkPrintOperation *op,
+                                                                                     cairo_surface_t *surface,
+                                                                                     cairo_t *cr);
+void                    _gtk_print_operation_platform_backend_preview_end_page       (GtkPrintOperation *op,
+                                                                                     cairo_surface_t *surface,
+                                                                                     cairo_t *cr);
 
 void _gtk_print_operation_set_status (GtkPrintOperation *op,
                                      GtkPrintStatus     status,
index d5389f92c78abd315fcb3fb574cb48586d557e0a..46ce889be9073b66b0990566b40808778c9e5ad3 100644 (file)
@@ -164,6 +164,7 @@ shell_command_substitute_file (const gchar *cmd,
 
 void
 _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+                                                     cairo_surface_t   *surface,
                                                      GtkWindow         *parent,
                                                      const gchar       *filename)
 {
@@ -175,6 +176,8 @@ _gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
   gchar *quoted_filename;
   GdkScreen *screen;
   GError *error = NULL;
+
+  cairo_surface_destroy (pop->surface);
  
   settings = gtk_settings_get_default ();
   g_object_get (settings, "gtk-print-preview-command", &preview_cmd, NULL);
@@ -570,17 +573,45 @@ _gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation
                                                              GtkPageSetup      *page_setup,
                                                              gdouble           *dpi_x,
                                                              gdouble           *dpi_y,
-                                                             const gchar       *target)
+                                                             gchar            **target)
 {
+  gchar *tmp_dir, *dir_template, *preview_filename;
   GtkPaperSize *paper_size;
   gdouble w, h;
   
+  dir_template = g_build_filename (g_get_tmp_dir (), "print-preview-XXXXXX", NULL);
+
+  /* use temp dirs because apps like evince need to have extensions
+   * to determine the mime type 
+   */
+  tmp_dir = mkdtemp(dir_template);
+  preview_filename = g_build_filename (tmp_dir, 
+                                      "Print Preview.pdf",
+                                      NULL);
+  g_free (dir_template);
+  *target = preview_filename;
+  
   paper_size = gtk_page_setup_get_paper_size (page_setup);
   w = gtk_paper_size_get_width (paper_size, GTK_UNIT_POINTS);
   h = gtk_paper_size_get_height (paper_size, GTK_UNIT_POINTS);
     
   *dpi_x = *dpi_y = 72;
-  return cairo_pdf_surface_create (target, w, h);
+  return cairo_pdf_surface_create (preview_filename, w, h);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+                                                         cairo_surface_t *surface,
+                                                         cairo_t *cr)
+{
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+                                                       cairo_surface_t *surface,
+                                                       cairo_t *cr)
+{
+  cairo_show_page (cr);
 }
 
 void
index c546ea4c835c9ed9ae061f416336779fed0b43f7..dd37581de9c4c02ab7eb16d2b6d7363bcbd97c5d 100644 (file)
 #define COBJMACROS
 #include "config.h"
 #include <math.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
 #include <stdlib.h>
 #include <cairo-win32.h>
 #include <glib.h>
@@ -58,6 +62,7 @@ typedef struct {
   int job_id;
   guint timeout_id;
 
+  cairo_surface_t *surface;
   GtkWidget *embed_widget;
 } GtkPrintOperationWin32;
 
@@ -492,9 +497,9 @@ win32_end_run (GtkPrintOperation *op,
   GlobalFree(op_win32->devmode);
   GlobalFree(op_win32->devnames);
 
-  cairo_surface_finish (op->priv->surface);
-  cairo_surface_destroy (op->priv->surface);
-  op->priv->surface = NULL;
+  cairo_surface_finish (op_win32->surface);
+  cairo_surface_destroy (op_win32->surface);
+  op_win32->surface = NULL;
 
   DeleteDC(op_win32->hdc);
   
@@ -1394,11 +1399,46 @@ create_application_page (GtkPrintOperation *op)
   return hpage;
 }
 
+static GtkPageSetup *
+create_page_setup (GtkPrintOperation *op)
+{
+  GtkPrintOperationPrivate *priv = op->priv;
+  GtkPageSetup *page_setup;
+  GtkPrintSettings *settings;
+  
+  if (priv->default_page_setup)
+    page_setup = gtk_page_setup_copy (priv->default_page_setup);
+  else
+    page_setup = gtk_page_setup_new ();
+
+  settings = priv->print_settings;
+  if (settings)
+    {
+      GtkPaperSize *paper_size;
+      
+      if (gtk_print_settings_has_key (settings, GTK_PRINT_SETTINGS_ORIENTATION))
+       gtk_page_setup_set_orientation (page_setup,
+                                       gtk_print_settings_get_orientation (settings));
+
+
+      paper_size = gtk_print_settings_get_paper_size (settings);
+      if (paper_size)
+       {
+         gtk_page_setup_set_paper_size (page_setup, paper_size);
+         gtk_paper_size_free (paper_size);
+       }
+
+      /* TODO: Margins? */
+    }
+  
+  return page_setup;
+}
+
 GtkPrintOperationResult
 _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
+                                                 gboolean show_dialog,
                                                  GtkWindow *parent,
-                                                 gboolean *do_print,
-                                                 GError **error)
+                                                 gboolean *do_print)
 {
   HRESULT hResult;
   LPPRINTDLGEXW printdlgex = NULL;
@@ -1407,14 +1447,17 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   GtkWidget *invisible = NULL;
   GtkPrintOperationResult result;
   GtkPrintOperationWin32 *op_win32;
+  GtkPrintOperationPrivate *priv;
   IPrintDialogCallback *callback;
   HPROPSHEETPAGE prop_page;
   
   *do_print = FALSE;
 
+  priv = op->priv;
+  
   op_win32 = g_new0 (GtkPrintOperationWin32, 1);
-  op->priv->platform_data = op_win32;
-  op->priv->free_platform_data = (GDestroyNotify) op_win32_free;
+  priv->platform_data = op_win32;
+  priv->free_platform_data = (GDestroyNotify) op_win32_free;
   
   if (parent == NULL)
     {
@@ -1428,7 +1471,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   if (!printdlgex)
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error (error,
+      g_set_error (&priv->error,
                   GTK_PRINT_ERROR,
                   GTK_PRINT_ERROR_NOMEM,
                   _("Not enough free memory"));
@@ -1451,7 +1494,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   if (!page_ranges) 
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
-      g_set_error (error,
+      g_set_error (&priv->error,
                   GTK_PRINT_ERROR,
                   GTK_PRINT_ERROR_NOMEM,
                   _("Not enough free memory"));
@@ -1499,27 +1542,27 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
     {
       result = GTK_PRINT_OPERATION_RESULT_ERROR;
       if (hResult == E_OUTOFMEMORY)
-       g_set_error (error,
+       g_set_error (&priv->error,
                     GTK_PRINT_ERROR,
                     GTK_PRINT_ERROR_NOMEM,
                     _("Not enough free memory"));
       else if (hResult == E_INVALIDARG)
-       g_set_error (error,
+       g_set_error (&priv->error,
                     GTK_PRINT_ERROR,
                     GTK_PRINT_ERROR_INTERNAL_ERROR,
                     _("Invalid argument to PrintDlgEx"));
       else if (hResult == E_POINTER)
-       g_set_error (error,
+       g_set_error (&priv->error,
                     GTK_PRINT_ERROR,
                     GTK_PRINT_ERROR_INTERNAL_ERROR,
                     _("Invalid pointer to PrintDlgEx"));
       else if (hResult == E_HANDLE)
-       g_set_error (error,
+       g_set_error (&priv->error,
                     GTK_PRINT_ERROR,
                     GTK_PRINT_ERROR_INTERNAL_ERROR,
                     _("Invalid handle to PrintDlgEx"));
       else /* E_FAIL */
-       g_set_error (error,
+       g_set_error (&priv->error,
                     GTK_PRINT_ERROR,
                     GTK_PRINT_ERROR_GENERAL,
                     _("Unspecified error"));
@@ -1539,13 +1582,25 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
     {
       DOCINFOW docinfo;
       int job_id;
-
+      double dpi_x, dpi_y;
+      cairo_t *cr;
+      GtkPageSetup *page_setup;
+
+      priv->print_context = _gtk_print_context_new (op);
+      page_setup = create_page_setup (op);
+      _gtk_print_context_set_page_setup (priv->print_context, page_setup);
+      g_object_unref (page_setup);
+      
       *do_print = TRUE;
 
-      op->priv->surface = cairo_win32_surface_create (printdlgex->hDC);
-      op->priv->dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
-      op->priv->dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
+      op_win32->surface = cairo_win32_surface_create (printdlgex->hDC);
+      dpi_x = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSX);
+      dpi_y = (double)GetDeviceCaps (printdlgex->hDC, LOGPIXELSY);
 
+      cr = cairo_create (op_win32->surface);
+      gtk_print_context_set_cairo_context (priv->print_context, cr, dpi_x, dpi_y);
+      cairo_destroy (cr);
+      
       memset( &docinfo, 0, sizeof (DOCINFOW));
       docinfo.cbSize = sizeof (DOCINFOW); 
       docinfo.lpszDocName = g_utf8_to_utf16 (op->priv->job_name, -1, NULL, NULL, NULL); 
@@ -1558,13 +1613,13 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
       if (job_id <= 0) 
        { 
          result = GTK_PRINT_OPERATION_RESULT_ERROR;
-         g_set_error (error,
+         g_set_error (&priv->error,
                       GTK_PRINT_ERROR,
                       GTK_PRINT_ERROR_GENERAL,
                     _("Error from StartDoc"));
          *do_print = FALSE;
-         cairo_surface_destroy (op->priv->surface);
-         op->priv->surface = NULL;
+         cairo_surface_destroy (op_win32->surface);
+         op_win32->surface = NULL;
          goto out; 
        } 
       
@@ -1609,18 +1664,101 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
   return result;
 }
 
-void 
-_gtk_print_operation_platform_backend_run_dialog_async (GtkPrintOperation          *op,
-                                                        GtkWindow                  *parent,
-                                                       GtkPrintOperationPrintFunc  print_cb)
+void
+_gtk_print_operation_platform_backend_launch_preview (GtkPrintOperation *op,
+                                                     cairo_surface_t   *surface,
+                                                     GtkWindow         *parent,
+                                                     const gchar       *filename)
 {
-  gboolean do_print;
+  HDC dc;
+  HENHMETAFILE metafile;
+  
+  dc = cairo_win32_surface_get_dc (surface);
+  cairo_surface_destroy (surface);
+  metafile = CloseEnhMetaFile (dc);
+  DeleteEnhMetaFile (metafile);
+  
+  ShellExecuteW (NULL, L"open", (gunichar2 *)filename, NULL, NULL, SW_SHOW);
+}
 
-  _gtk_print_operation_platform_backend_run_dialog (op, parent, &do_print, NULL);
-  if (do_print)
-    print_cb (op, parent, FALSE);
-  else
-    _gtk_print_operation_set_status (op, GTK_PRINT_STATUS_FINISHED_ABORTED, NULL);
+void
+_gtk_print_operation_platform_backend_preview_start_page (GtkPrintOperation *op,
+                                                         cairo_surface_t *surface,
+                                                         cairo_t *cr)
+{
+  HDC dc = cairo_win32_surface_get_dc (surface);
+  StartPage (dc);
+}
+
+void
+_gtk_print_operation_platform_backend_preview_end_page (GtkPrintOperation *op,
+                                                       cairo_surface_t *surface,
+                                                       cairo_t *cr)
+{
+  /* TODO: This doesn't actually seem to work.
+   * Do enhanced metafiles really support multiple pages?
+   */
+  HDC dc = cairo_win32_surface_get_dc (surface);
+  EndPage (dc);
+}
+
+cairo_surface_t *
+_gtk_print_operation_platform_backend_create_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             gdouble           *dpi_x,
+                                                             gdouble           *dpi_y,
+                                                             gchar            **target)
+{
+  GtkPaperSize *paper_size;
+  double w, h;
+  HDC metafile_dc;
+  RECT rect;
+  char *template;
+  char *filename;
+  gunichar2 *filename_utf16;
+  int fd;
+
+  template = g_build_filename (g_get_tmp_dir (), "prXXXXXX", NULL);
+  fd = g_mkstemp (template);
+  close(fd);
+
+  filename = g_strconcat (template, ".emf", NULL);
+  g_free (template);
+  
+  filename_utf16 = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+  g_free (filename);
+
+  paper_size = gtk_page_setup_get_paper_size (page_setup);
+  w = gtk_paper_size_get_width (paper_size, GTK_UNIT_MM);
+  h = gtk_paper_size_get_height (paper_size, GTK_UNIT_MM);
+  
+  rect.left = 0;
+  rect.right = w*100;
+  rect.top = 0;
+  rect.bottom = h*100;
+  
+  metafile_dc = CreateEnhMetaFileW (NULL, filename_utf16,
+                                   &rect, L"Gtk+\0Print Preview\0\0");
+  if (metafile_dc == NULL)
+    {
+      g_warning ("Can't create metafile");
+      return NULL;
+    }
+
+  *target = (char *)filename_utf16;
+  
+  *dpi_x = (double)GetDeviceCaps (metafile_dc, LOGPIXELSX);
+  *dpi_y = (double)GetDeviceCaps (metafile_dc, LOGPIXELSY);
+
+  return cairo_win32_surface_create (metafile_dc);
+}
+
+void
+_gtk_print_operation_platform_backend_resize_preview_surface (GtkPrintOperation *op,
+                                                             GtkPageSetup      *page_setup,
+                                                             cairo_surface_t   *surface)
+{
+  /* TODO: Implement */
 }
 
 GtkPageSetup *
index 78d68aa1b802052ef13a5d142020cf05f684d6b4..b39ac1f94aa242ee19f76dddfea13ecb53e399d6 100644 (file)
@@ -387,13 +387,14 @@ preview_print_idle_done (gpointer data)
   
   op = GTK_PRINT_OPERATION (pop->preview);
 
+  cairo_surface_finish (pop->surface);
+  /* Surface is destroyed in launch_preview */
   _gtk_print_operation_platform_backend_launch_preview (op,
+                                                       pop->surface,
                                                        pop->parent,
                                                        pop->filename);
 
   g_free (pop->filename);
-  cairo_surface_finish (pop->surface);
-  cairo_surface_destroy (pop->surface);
 
   gtk_print_operation_preview_end_preview (pop->preview);
   g_free (pop);
@@ -417,7 +418,8 @@ preview_print_idle (gpointer data)
   gtk_print_operation_preview_render_page (pop->preview, pop->page_nr);
   
   cr = gtk_print_context_get_cairo_context (pop->print_context);
-  cairo_show_page (cr);
+  _gtk_print_operation_platform_backend_preview_end_page (op, pop->surface,
+                                                         cr);
   
   /* TODO: print out sheets not pages and follow ranges */
   pop->page_nr++;
@@ -436,8 +438,14 @@ preview_got_page_size (GtkPrintOperationPreview *preview,
                       PreviewOp                *pop)
 {
   GtkPrintOperation *op = GTK_PRINT_OPERATION (preview);
+  cairo_t *cr;
 
   _gtk_print_operation_platform_backend_resize_preview_surface (op, page_setup, pop->surface);
+
+  cr = gtk_print_context_get_cairo_context (pop->print_context);
+  _gtk_print_operation_platform_backend_preview_start_page (op, pop->surface,
+                                                           cr);
+
 }
 
 static void
@@ -462,28 +470,12 @@ gtk_print_operation_preview_handler (GtkPrintOperation        *op,
                                     GtkWindow                *parent)
 {
   gdouble dpi_x, dpi_y;
-  gchar *tmp_dir;
-  gchar *dir_template;
-  gchar *preview_filename;
   PreviewOp *pop;
   GtkPageSetup *page_setup;
   cairo_t *cr;
 
-  dir_template = g_build_filename (g_get_tmp_dir (), "print-preview-XXXXXX", NULL);
-
-  /* use temp dirs because apps like evince need to have extensions
-   * to determine the mime type 
-   */
-  tmp_dir = mkdtemp(dir_template);
-
-  preview_filename = g_build_filename (tmp_dir, 
-                                      "Print Preview.pdf",
-                                      NULL);
-  
-  g_free (dir_template);
-
   pop = g_new0 (PreviewOp, 1);
-  pop->filename = preview_filename;
+  pop->filename = NULL;
   pop->preview = preview;
   pop->parent = parent;
 
@@ -493,7 +485,7 @@ gtk_print_operation_preview_handler (GtkPrintOperation        *op,
     _gtk_print_operation_platform_backend_create_preview_surface (op,
                                                                  page_setup,
                                                                  &dpi_x, &dpi_y,
-                                                                 pop->filename);
+                                                                 &pop->filename);
 
   cr = cairo_create (pop->surface);
   gtk_print_context_set_cairo_context (op->priv->print_context, cr,
@@ -2403,6 +2395,7 @@ gtk_print_operation_run (GtkPrintOperation        *op,
 
       priv->is_sync = !priv->allow_async;
     }
+#ifndef G_OS_WIN32
   else if (priv->allow_async)
     {
       priv->is_sync = FALSE;
@@ -2412,6 +2405,7 @@ gtk_print_operation_run (GtkPrintOperation        *op,
                                                              print_pages);
       result = GTK_PRINT_OPERATION_RESULT_IN_PROGRESS;
     }
+#endif
   else
     {
       priv->is_sync = TRUE;
index e8d6a0e5fd43295fd058340a0c26bd2351906fdf..ee839c1d5396539fb6511711f1d4e8ce8b2aab6f 100644 (file)
@@ -497,7 +497,7 @@ preview_got_page_size (GtkPrintOperationPreview *preview,
 
   dpi_x = pop->area->allocation.width/w;
   dpi_y = pop->area->allocation.height/h;
-  
+
   if (fabs (dpi_x - pop->dpi_x) > 0.001 ||
       fabs (dpi_y - pop->dpi_y) > 0.001)
     {
@@ -683,7 +683,7 @@ do_print (GtkAction *action)
 #if 0
   gtk_print_operation_set_allow_async (print, TRUE);
 #endif
-  gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PREVIEW, GTK_WINDOW (main_window), NULL);
+  gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW (main_window), NULL);
 
   g_object_unref (print);
 }